<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
      <el-form-item label="视频名字" prop="roleName">
        <el-input v-model="videoFindName" placeholder="请输入查找的视频名字" clearable style="width: 260px"
                  @keyup.enter.native="handleQuery"/>
      </el-form-item>
      <el-form-item label="创建时间">
        <el-date-picker v-model="dateRange" style="width: 260px" value-format="yyyy-MM-dd" type="daterange"
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
        >新增
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
                   @click="handleDelete">删除
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
        >导出
        </el-button>
      </el-col>
    </el-row>
    <el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center"/>
      <el-table-column prop="icon" label="封面图" align="center" width="300">
        <template class="avatar-wrapper" slot-scope="scope">
          <img :src="scope.row.coverUrl" class="videoHadnelImg">
          <!-- <i class="el-icon-caret-bottom" /> -->
        </template>
      </el-table-column>
      <el-table-column label="文件名" prop="name" width="120" class="fileNames">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.file_name" :value="scope.row.name"/>
        </template>
      </el-table-column>
      <el-table-column prop="task" label="状态" width="280" align="center">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.process_status" :value="scope.row.task"/>
        </template>
      </el-table-column>
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.createTime) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="制作进度" align="center" prop="processProgress" width="180"/>
      <!--      <el-table-column label="下载链接" align="center" prop="videoUrl" width="180" />-->
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope" v-if="scope.row.roleId !== 1">
          <el-button size="mini" type="text" @click="handDownload(scope.row.asyncQiniu,scope.row.name)"
                     :disabled="canDownload(scope.row.updateTime,scope.row.asyncQiniu)"
          >{{downloadOrexpire(scope.row.updateTime,scope.row.asyncQiniu) }}
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getListTask"
    />
    <el-dialog v-loading="openWorkLoad" element-loading-text="任务创建中，请勿刷新页面。。。" :title="title"
               :visible.sync="open" width="1060px" append-to-body>
      <template>
        <el-text class="mx-1">上传视频画质在</el-text>
        <el-text class="red">380P~1080P</el-text>
        <el-text class="mx-1">之间，视频时长在</el-text>
        <el-text class="red" type="danger">一分钟内</el-text>
        <el-text class="green" type="primary">需要上传超过一分钟、超过50M、超过1080P</el-text>
        <el-text class="mx-1">的客户，请与专属客服联系，文件上传过程中</el-text>
        <el-text class="red" type="danger">禁止关闭浏览器和窗口</el-text>
      </template>
      <el-checkbox-group v-model="checkList">
        <el-checkbox v-model="checkdata.denoise" label="音频降噪" size="large" border disabled :checked="true"
                     :change="checkChange()"/>
        <el-checkbox v-model="checkdata.disturb" label="编码打乱" size="large" border :checked="true" disabled/>
        <el-checkbox v-model="checkdata.AntiAI" label="反AI算法" size="large" border :checked="true" disabled/>
        <el-checkbox v-model="checkdata.realTime" label="实时配音" size="large" border :checked="true" disabled/>
        <el-checkbox v-model="checkdata.captions" label="智能字幕" size="large" border :checked="true" disabled/>
        <el-checkbox v-model="checkdata.translate" label="实时翻译" size="large" border :checked="true" disabled/>
        <el-checkbox v-model="checkdata.examine" label="审核评分" size="large" border :checked="true" disabled/>
        <el-checkbox v-model="checkdata.SoundCloning" label="声音克隆" size="large" border :checked="true" disabled/>
      </el-checkbox-group>
      <template @click="editCropper()">
        <div style="align-items: center; width: 200px; float: left;">
          <img v-bind:src="moteimg" title="选择模特" class="motelimg"/>
          <el-button type="primary" @click="checkModel"
                     style="width: 160px; margin-left: 20px;">选择模特
          </el-button>
        </div>
        <div class="sounAndVideo">
          <div class="sounAndVideol">
            <p>点击声音选中并试听</p>
            <el-button class="soundButtion" icon="el-icon-headset"
                       v-for="(item,index) in musicRegion" :type="item.id == userTask.wyVoiceParam ? 'success' : 'text'"
                       @click="playVi(index,item)">
              {{
                item.isAdvanced == 0 ? "基础" + item.displayName2 + "" + item.displayName : "高级" + item.displayName2 + "" + item.displayName
              }}
            </el-button>
          </div>
          <div class="sounAndVideor">
            <el-upload ref="uvders" :action="alioss" :show-file-list="true"
                       :before-upload="gsbeforeUpload" :multiple="true" :auto-upload="upload"
                       :on-success="handleSuccess" :on-error="handleError" :data="postData" :file-list="fileList">
                            <template #trigger>
                              <el-button class="ml-3" type="primary" style="width: 380px;">
                                选择视频
                                <i class="el-icon-upload el-icon--right"></i>
                              </el-button>
                            </template>
            </el-upload>

          </div>
        </div>
      </template>
      <el-row style="clear: both">
        <el-select v-model="userTask.sourceLang" placeholder="选择视频语言" style="width: 240px;margin-right: 20px">
          <el-option
            v-for="item in sourceLang"
            :key="item.code"
            :label="item.description"
            :value="item.code"
          />
        </el-select>
        <el-select v-model="userTask.lang" placeholder="选择目标语言语言" style="width: 240px;margin-right: 20px">
          <el-option
            v-for="item in targetLang"
            :key="item.code"
            :label="item.description"
            :value="item.code"
          />
        </el-select>
        <el-button class="ml-3" type="success" @click="submitUpload">
          开始上传并制作视频
        </el-button>
      </el-row>
    </el-dialog>
    <el-dialog :title="model" :visible.sync="openmodel" width="800px" append-to-body>
      <el-row :gutter="20" class="image-gallery">
        <el-col :span="8" v-for="(item, index) in galleryItems" :key="index">
          <el-card class="box-card">
            <div slot="header" class="clearfix">
              <span>{{ item.name }}</span>
            </div>
            <div class="card-body">
              <img :src="item.url" :alt="item.name" class="gallery-image"
                   @click="handleCardClick(item)">
            </div>
            <div v-if="isHovered(index)" class="overlay">
            </div>
          </el-card>
        </el-col>
      </el-row>
      <pagination
        v-show="modeltotal>0"
        :total="modeltotal"
        :page.sync="modelParms.pageNum"
        :limit.sync="modelParms.pageSize"
        @pagination="getAimodel"
      />
    </el-dialog>
    <el-button @click="addTTS()">增加音频</el-button>
  </div>
</template>
<script>
import {genUpToken} from '../../utils/tk64';
import axios from 'axios'
import crypto from 'crypto'
import {getUserProfile} from "@/api/system/user";
import {listGs} from '@/api/system/gs'
import {listAimodel} from '@/api/system/aimodel'
import {addTaskIno, listTask, addList} from '@/api/system/task'
import {saveAs} from 'file-saver'
import {addSysVoice, recommend} from '@/api/system/SysVoice'

export default {
  name: "Video",
  dicts: ['process_status', "file_name"],
  // components: {
  //   Plus
  // },
  data() {
    return {
      // 遮罩层
      dialogVisible: "",
      dialogImageUrl: "",
      loading: false,
      openWorkLoad: true,
      roleList: [
        {
          coverUrl: ""
        }
      ],
      total: 0,
      modeltotal: 0,
      gs: {
        ak: null,
        as: null
      },
      targetLang: {},
      sourceLang: {},
      tarLang: "",
      sourLang: "",
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      hover: false,
      title: "批量添加视频任务",
      // 是否显示弹出层
      open: false,
      //查找的视频名字
      videoFindName: "",
      model: "选择合适的模特",
      openmodel: false,
      fileList: [],
      actionPath: "",
      postData: {
        "key": null,
        "OSSAccessKeyId": "",
        "policy": "",
        "signature": "",
        "callback": "",
        "success_action_status": 200
      },
      upload: false,
      moteimg: "/static/img/profile.473f5971.jpg",
      checkdata: {
        denoise: true,
        disturb: true,
        AntiAI: true,
        realTime: true,
        captions: true,
        translate: true,
        SoundCloning: true,
        examine: false
      },
      galleryItems: [],
      checkList: [],
      hoverIndexes: new Set(),
      musicRegion: [
        {code: "", description: "男声沉浸美式英语", descriptionEn: "", descriptionPt: ""}
      ],
      user: {},
      userCurrentFileData: {
        fileName: "",
        filePath: "",
        status: ""
      },
      temres: null,
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        roleName: undefined,
        roleKey: undefined,
        status: undefined
      },
      modelParms: {
        pageNum: 1,
        pageSize: 12,
        roleName: undefined,
        roleKey: undefined,
        status: undefined
      },
      // 日期范围
      dateRange: [],
      alioss: "",
      tempFilePath: "",
      userTask: {
        path: "",
        task: "-1",
        aimodel: "",
        sourceLang: "",
        lang: "",
        wyVoiceParam: "",
        fontParam: "default",
        fontSize: 40,
        captions: true,
        removeBgAudio: true,
        idProject: 0,
        idWorks: 0,
        name: ""
      },
      ijcot: "",
      isfirst: 0,
      tmdata: null,
      batch: {
        userTask: null,
        workpath: []
      }
    }
  },
  created() {
    this.getUser()
    this.getListTask()
  },
  mounted() {
    this.timer = setInterval(() => {
      // this.currentTime = new Date().toLocaleTimeString();
      this.getListTask()
    }, 5000); // 每秒更新一次时间
  },
  beforeDestroy() {
    clearInterval(this.timer); // 组件销毁前清除定时器
  },
  methods: {
    async handleAdd() {
      //获取签名凭证
      this.listgsinfo()
      //模特语音
      this.queryTLang()
      //模特列表
      this.getAimodel()
      this.open = true;
      this.openWorkLoad = false
    },
    async listgsinfo() {
      await listGs().then(res => {
        if (res.code == 200) {
          this.gs.as = res.rows[0].gsas;
          this.gs.ak = res.rows[0].gsak;
        }
      }).catch(e => {
        console.log(e)
      })
    },
    async getListTask() {
      if (this.isfirst == 0) {
        this.loading = true;
        this.isfirst++;
      }
      console.log("自动加载进度")
      await listTask(this.addDateRange(this.queryParams, this.dateRange)).then(res => {
        this.roleList = res.rows;
        this.total = res.total;
      })
      this.loading = false;
    },

    async getAimodel() {
      this.loading = true;
      await listAimodel(this.addDateRange(this.modelParms, this.dateRange)).then(res => {
        if (res.code == 200) {
          this.galleryItems = res.rows;
          this.modeltotal = res.total;
        }
      }).catch(e => {
        this.$modal.msgError("模特今天没上班，请联系管理员，err:30046")
      })
      this.loading = false;
    },
    async queryTLang() {
      this.loading = true;
      //获取目标语言
      let bodystr = {"text": "Lang"}
      let url = "gsap/enum/query2"
      await this.gssign(bodystr, url).then(res => {
        this.temres = res.data
      }).catch(e => {
        console.log(e)
      })

      if (this.temres.code == "1000") {
        this.targetLang = this.temres.body
      }
      //获取支持的源语言
      bodystr = {"text": "sourceLang"}
      await this.gssign(bodystr, url).then(res => {
        if (res.data.code == "1000") {
          this.sourceLang = res.data.body
        }
      }).catch(e => {
        console.log(e)
      })
      await recommend().then(res => {
        this.musicRegion = res
      })

      this.loading = false;
    },
    async addTTS() {
      for (let i = 0; i < this.musicRegion.length; i++) {
        await addSysVoice(this.musicRegion[i])
      }
    },

    gssign(bodystr, url) {
      this.loading = true;
      let body = JSON.stringify(bodystr)
      let sign = this.my_md5(this.my_md5(body) + this.gs.as)
      var instance = axios.create({
        headers: {
          'Content-type': 'application/json',
          'AppKey': this.gs.ak,
          'AppSign': sign,
        }
      });
      return instance.post(url, body);
      this.loading = false
    },
    //上传准备并鉴权
    async gsbeforeUpload(file) {
      this.openWorkLoad = true;
      //根据服务端前置验证用户余额
      if (file.type.indexOf("video/") == -1) {
        this.$modal.msgError("只能上传MP4、AVI、MKV、MOV、FLV、TS、MPG。");
        this.$refs.uvders.abort()
        return
      }
      if (file.size > (50 * 1024 * 1024)) {
        this.$modal.msgError("文件不能超过50M");
        this.$refs.uvders.abort()
        return
      }
      let currentDate = new Date();
      let url = "gsap/gateway/ve/file/upload/policy/apply"
      let body = {
        "nonce": this.user.userName + currentDate.getFullYear() + String(currentDate.getMonth() + 1).padStart(2, '0') + String(currentDate.getDate()).padStart(2, '0'),
      }
      await this.gssign(body, url).then(res => {
        if (res.data.code == "1000") {
          let policyupload = res.data.body
          this.postData.key = policyupload.dir + file.name
          this.postData.OSSAccessKeyId = policyupload.accessid
          this.postData.policy = policyupload.policy
          this.postData.signature = policyupload.signature
          this.postData.callback = policyupload.base64CallbackBody
          // formData.append("file", file);
          this.alioss = policyupload.host
          //保存文件地址，如果上传成功则记录文件
          // this.userTask.path = policyupload.urlPrefix + file.name
          //提交task并保存记录
          this.batch.workpath.push(policyupload.urlPrefix + file.name)
        }
      }).catch(e => {
        console.log(e)
      })

    },
    handleError(error, file, fileList) {
      console.error('上传失败:', error);
    },
    canDownload(date,qn) {
    if (qn != null && qn !== "") {
      return false;
    }
    if (date == "" || date == undefined || date == null) {
      return true;
    }
    // const inputDate = new Date(date);
    // const currentTime = new Date();
    // const thirtyMinutesAgo = new Date(currentTime.getTime() - 29 * 60 * 1000);
    // return inputDate < thirtyMinutesAgo;

    },
    downloadOrexpire(date,qn) {
      if (qn != null && qn !== "") {
        return "下载"
      }
      if (date === "" || date === undefined || date == null) {
        return "视频制作中。。";
      }
      return "链接准备中。。"
    },
    async handDownload(file, name) {
      try {
        const response = await axios.get(file, {
          responseType: 'blob'  // 告诉axios返回的是一个Blob对象
        });
        const blob = new Blob([response.data], {type: response.headers['content-type']});
        saveAs(blob, name);  // 替换为实际的文件名和扩展名
      } catch (error) {
        console.error('Error downloading the file:', error);
      }

    },
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 50 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`);
    },
    //创建视频任务id,不做剪辑和AI动作
    async createViWork() {
      let url = "gsap/gateway/ve/work/free";
      let body = {
        "urls": this.userTask.path,
        "needChineseOcclude": 1,
        "videoInpaintLang": "all",
        "sourceLang": this.userTask.sourceLang,
        "lang": this.userTask.lang,
        "needWanyin": 1,
        "wyTaskType": "FULL",
        "wyNeedText": 1,
        "wyVoiceParam": {
          "id": this.userTask.wyVoiceParam,//音频的id
          "font_param": {
            "style": "default",
            "font_size": 40,
            "position": 0.727
          }
        },
        "removeBgAudio": 2
      }
      let idcode = 0;
      await this.gssign(body, url).then(res => {
        let rdta = res.data.body
        if (res.data.code == "1000") {
          if (rdta.idProject !== undefined && rdta.idProject !== "") {
            this.userTask.idProject = rdta.idProject;
          }
          if (rdta.idWorks !== undefined && rdta.idWorks !== "") {
            this.userTask.idWorks = rdta.idWorks;
          }
        }
        return this.userTask;
      }).catch(e => {
        console.log(e)
      }).finally(() => {
        console.log("返回结果集" + idcode)
        this.ijcot = idcode
      })
      return this.userTask;
    },
    async handleSuccess() {
      // this.tmdata =await this.createViWork()
      // let les = _.cloneDeep(this.tmdata);
      this.batch.userTask = this.userTask;
      const response = addList(this.batch);
      this.batch.userTask.length = 0
      this.open = false
    },
    //查询结果
    workstatus() {
      let body = {"idWorks": [483255350]}
      //227661321
      //trace:"292a1b2288e842298798f265dc34444a"
      let url = "gsap/gateway/ve/work/status"
      this.gssign(body, url).then(res => {
      }).catch(e => {
        console.log(e)
      })
    },

    getlist() {
      this.loading = false
    },
    handleQuery() {

    },
    resetQuery() {

    },

    handleDelete() {

    },
    handleExport() {

    },
    checkChange() {
    },
    opents() {
      console.log("this is open")
    },

    isHovered(index) {
      // 根据索引判断卡片是否被悬停
      return this.hoverIndexes.has(index);
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.roleId)
      this.single = selection.length != 1
      this.multiple = !selection.length
    },
    submitUpload() {
      this.$refs.uvders.submit()
    },
    checkModel() {
      this.openmodel = true
    },
    handleCardClick(model) {
      this.moteimg = model.url
      this.userTask.aimodel = model.id
      this.openmodel = false
    },
    /**
     * 七牛云生产随机不重复的名称
     * @returns {string}
     */
    generateRandomString() {
      const crypto = require('crypto');
      const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
      const charactersLength = characters.length;
      const result = [];
      const usedChars = new Set();
      while (result.length < length) {
        const randomIndex = crypto.randomInt(0, charactersLength);
        const randomChar = characters[randomIndex];

        if (!usedChars.has(randomChar)) {
          result.push(randomChar);
          usedChars.add(randomChar);
        }
      }
      return result.join('');
    },
    getUser() {
      getUserProfile().then(response => {
        this.user = response.data;
      });
    },
    qiniukey() {
      var token;
      var policy = {};
      var bucketName = 'ueditor-sunne';
      var AK = 'UZFlrDtVCilyWKpn8xHDrOMlp2SeFa97qr1HgiuE';
      var SK = 'T5XTHw6SIsSF5X3vz8ZW-U6KzQFJEUQfhxURMSsK';
      var deadline = Math.round(new Date().getTime() / 1000) + 3600;
      policy.scope = bucketName;
      policy.deadline = deadline;
      token = genUpToken(AK, SK, policy);
      this.postData.token = token;
    },
    editCropper() {
    },
    playVi(index, item) {
      var audio = new Audio(item.demoUrl);
      audio.play();
      this.$modal.msgSuccess("正在试听:" + item.isAdvanced == 0 ? "基础" + item.displayName2 + "" + item.displayName : "高级" + item.displayName2 + "" + item.displayName)
      this.userTask.wyVoiceParam = item.rid
    },
    my_md5(str) {
      var md5 = crypto.createHash('md5');
      return md5.update(str).digest('hex');
    },
  }
}
</script>
<style scoped>
.videoHadnelImg {
  width: 100px;
  height: 100px;
  object-fit: cover;
}

.fileNames {
  overflow: hidden;
  /* 隐藏超出部分 */
  text-overflow: ellipsis;
  /* 使用省略号表示超出部分 */
  white-space: nowrap;
  /* 禁止文本换行 */
  width: 100px;
  height: 100px;
}

.red {
  color: #FF0033;
}

.green {
  color: #0033FF;
}

.image-gallery {
  margin: 20px;
}

.gallery-image {
  width: 100%;
  height: auto;
  display: block;
}

.motelimg {
  margin: 20px;
  width: 160px;
  height: 240px;
  object-fit: cover;
  border-radius: 46px;
  float: left;
}

.clboth {
  clear: both;
}

.box-card {
  transition: all 0.3s ease;
  /* 添加过渡效果 */
  margin-bottom: 20px;
}

.box-card:hover {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  transform: translateY(-5px);
  cursor: pointer;
  background-color: #00FFFF;
}

.card-body {
  position: relative;
  /* 确保内部元素可以定位 */
}

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.2);
  /* 半透明背景 */
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.3s ease;
  /* 添加过渡效果 */
}

.sounAndVideo {
  width: 800px;
  height: 480px;
  margin-top: 20px;
  float: left;
}

.sounAndVideol {
  width: 430px;
  height: 460px;
  background-color: #fff;
  float: left;
  overflow: auto;
}

.sounAndVideor {
  width: 360px;
  height: 460px;
  float: left;
  overflow: auto;
}

.soundButtion {
  margin: 5px 5px 5px 5px;
}
</style>
